home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / utilit~1 / futilsrc.zoo / fileutil / lib / makepath.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-19  |  5.2 KB  |  209 lines

  1. /* makepath.c -- Ensure that a directory path exists.
  2.    Copyright (C) 1990 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /* Written by David MacKenzie <djm@ai.mit.edu> and
  19.    Jim Meyering <meyering@cs.utexas.edu>. */
  20.  
  21. #ifdef __GNUC__
  22. #define alloca __builtin_alloca
  23. #else
  24. #ifdef sparc
  25. #include <alloca.h>
  26. #else
  27. #ifdef _AIX
  28.  #pragma alloca
  29. #else
  30. char *alloca ();
  31. #endif
  32. #endif
  33. #endif
  34.  
  35. #include <stdio.h>
  36. #include <sys/types.h>
  37. #include <sys/stat.h>
  38. #ifdef POSIX
  39. #include <unistd.h>
  40. #endif
  41. #if !defined(S_ISDIR) && defined(S_IFDIR)
  42. #define    S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
  43. #endif
  44.  
  45. #ifdef STDC_HEADERS
  46. #include <errno.h>
  47. #include <stdlib.h>
  48. #else
  49. extern int errno;
  50. #endif
  51.  
  52. #if defined(USG) || defined(STDC_HEADERS)
  53. #include <string.h>
  54. #define index strchr
  55. #else
  56. #include <strings.h>
  57. #endif
  58.  
  59. void error ();
  60.  
  61. /* Ensure that the directory CONST_DIRPATH exists
  62.    (remove any trailing slashes from CONST_DIRPATH before calling).
  63.  
  64.    Make any leading directories that don't already exist, with
  65.    permissions PARENT_MODE.
  66.    If the last element of CONST_DIRPATH does not exist, create it as
  67.    a new directory with permissions MODE.
  68.    If OWNER and GROUP are non-negative, make them the UID and GID of
  69.    created directories.
  70.    If VERBOSE_FMT_STRING is nonzero, use it as a printf format
  71.    string for printing a message after successfully making a directory,
  72.    with the name of the directory that was just made as an argument.
  73.  
  74.    Return 0 if CONST_DIRPATH exists as a directory with the proper
  75.    ownership and permissions when done, otherwise 1. */
  76.  
  77. int
  78. make_path (const_dirpath, mode, parent_mode, owner, group, verbose_fmt_string)
  79.      char *const_dirpath;
  80.      int mode;
  81.      int parent_mode;
  82.      int owner;
  83.      int group;
  84.      char *verbose_fmt_string;
  85. {
  86.   char *dirpath;        /* A copy we can scribble nulls on. */
  87.   struct stat stats;
  88.  
  89.   dirpath = alloca (strlen (const_dirpath) + 1);
  90.   strcpy (dirpath, const_dirpath);
  91.  
  92.   if (stat (dirpath, &stats))
  93.     {
  94.       char *slash;
  95.       int tmp_mode;
  96.       int need_to_re_protect;    /* Should intermediate dirs be unwritable? */
  97.       struct ptr_list
  98.       {
  99.     char *dirname_end;
  100.     struct ptr_list *next;
  101.       };
  102.       struct ptr_list *p, *leading_dirs = NULL;
  103.  
  104.       if ((parent_mode & 0300) == 0300)
  105.     {
  106.       /* We will have write and execute permission for created dirs. */
  107.       tmp_mode = parent_mode;
  108.       need_to_re_protect = 0;
  109.     }
  110.       else
  111.     {
  112.       tmp_mode = 0700;
  113.       need_to_re_protect = 1;
  114.     }
  115.  
  116.       slash = dirpath;
  117.       while (*slash == '/')
  118.     slash++;
  119.       while (slash = index (slash, '/'))
  120.     {
  121.       *slash = '\0';
  122.       if (stat (dirpath, &stats))
  123.         {
  124.           if (mkdir (dirpath, tmp_mode))
  125.         {
  126.           error (0, errno, "cannot make directory `%s'", dirpath);
  127.           return 1;
  128.         }
  129.           else
  130.         {
  131.           if (verbose_fmt_string != NULL)
  132.             error (0, 0, verbose_fmt_string, dirpath);
  133.  
  134.           if ((owner >= 0 && group >= 0)
  135.               && chown (dirpath, owner, group))
  136.             {
  137.               error (0, errno, "%s", dirpath);
  138.               return 1;
  139.             }
  140.           if (need_to_re_protect)
  141.             {
  142.               struct ptr_list *new = alloca (sizeof (struct ptr_list));
  143.               new->dirname_end = slash;
  144.               new->next = leading_dirs;
  145.               leading_dirs = new;
  146.             }
  147.         }
  148.         }
  149.       else if (!S_ISDIR (stats.st_mode))
  150.         {
  151.           error (0, 0, "`%s' exists but is not a directory", dirpath);
  152.           return 1;
  153.         }
  154.       *slash++ = '/';
  155.  
  156.       /* Avoid unnecessary calls to `stat' when given
  157.          pathnames containing multiple adjacent slashes.  */
  158.       while (*slash == '/')
  159.         slash++;
  160.     }
  161.  
  162.       if (mkdir (dirpath, mode))
  163.     {
  164.       error (0, errno, "cannot make directory `%s'", dirpath);
  165.       return 1;
  166.     }
  167.       if (verbose_fmt_string != NULL)
  168.     error (0, 0, verbose_fmt_string, dirpath);
  169.  
  170.       if ((owner >= 0 && group >= 0) && chown (dirpath, owner, group))
  171.     {
  172.       error (0, errno, "%s", dirpath);
  173.       return 1;
  174.     }
  175.  
  176.       /* If the mode for leading directories didn't include owner "wx"
  177.      privileges, we have to reset their protections to the correct
  178.      value.  */
  179.       for (p = leading_dirs; p != NULL; p = p->next)
  180.     {
  181.       *(p->dirname_end) = '\0';
  182.       if (chmod (dirpath, parent_mode))
  183.         {
  184.           error (0, errno, "%s", dirpath);
  185.           return 1;
  186.         }
  187.     }
  188.     }
  189.  
  190.   /* We get here if the entire path already exists. */
  191.  
  192.   else if (!S_ISDIR (stats.st_mode))
  193.     {
  194.       error (0, 0, "`%s' exists but is not a directory", dirpath);
  195.       return 1;
  196.     }
  197.   else if (chmod (dirpath, mode))
  198.     {
  199.       error (0, errno, "%s", dirpath);
  200.       return 1;
  201.     }
  202.   else if ((owner >= 0 && group >= 0) && chown (dirpath, owner, group))
  203.     {
  204.       error (0, errno, "%s", dirpath);
  205.       return 1;
  206.     }
  207.   return 0;
  208. }
  209.